/**
 * 高德地图API服务模块
 * 提供周边POI搜索功能
 */

import type { Restaurant, Cuisine } from './types';

// 高德地图API配置
const AMAP_CONFIG = {
  baseUrl: 'https://restapi.amap.com/v3/place/around',
  key: process.env.NEXT_PUBLIC_MAP_API_KEY || '',
  radius: 3000, // 固定3公里搜索范围
  extensions: 'base',
} as const;

// 高德地图API响应类型定义
interface AmapPOI {
  id: string;
  name: string;
  type: string;
  typecode: string;
  address: string;
  location: string;
  distance?: string;
  tel?: string;
  business?: {
    rating?: string;
    cost?: string;
  };
}

interface AmapResponse {
  status: string;
  info: string;
  infocode: string;
  count: number;
  pois: AmapPOI[];
}

// 错误码映射
const ERROR_MESSAGES: Record<string, string> = {
  INVALID_USER_KEY: 'API密钥无效',
  INVALID_USER_SIGNATURE: 'API签名无效',
  USERKEY_PLAT_NOMATCH: 'API密钥与平台不匹配',
  IP_QUERY_OVER_LIMIT: 'IP查询超限',
  NOT_SUPPORT_HTTPS: '不支持HTTPS请求',
  INSUFFICIENT_PRIVILEGES: '权限不足',
  USER_KEY_RECYCLED: 'API密钥已被回收',
  QPS_HAS_EXCEEDED_THE_LIMIT: 'QPS超限',
  GATEWAY_TIMEOUT: '网关超时',
  INVALID_PARAMS: '请求参数非法',
  MISSING_REQUIRED_PARAMS: '缺少必填参数',
  ILLEGAL_REQUEST: '请求协议非法',
  UNKNOWN_ERROR: '未知错误',
};

// 菜系类型映射 - 将高德地图的POI类型映射到应用的菜系类型
const TYPE_TO_CUISINE_MAP: Record<string, Cuisine[]> = {
  '050000': ['川菜', '湘菜'], // 餐饮服务
  '050100': ['川菜'], // 中餐厅
  '050101': ['川菜'], // 川菜
  '050102': ['粤菜'], // 粤菜
  '050103': ['湘菜'], // 湘菜
  '050200': ['西餐'], // 外国餐厅
  '050201': ['西餐'], // 西餐厅
  '050300': ['快餐'], // 快餐厅
  '050301': ['快餐'], // 快餐
  '050400': ['火锅'], // 火锅店
  '050500': ['日料'], // 日本料理
  '050600': ['韩料'], // 韩国料理
  '050700': ['轻食'], // 茶艺馆
  '050800': ['麻辣烫'], // 冷饮店
};

// 验证和清理菜系数据
function validateAndCleanCuisine(cuisines: Cuisine[]): Cuisine[] {
  if (!cuisines || cuisines.length === 0) {
    return ['其他'];
  }
  
  // 过滤掉无效的菜系
  const validCuisines = cuisines.filter(cuisine => {
    // 检查是否为有效的Cuisine类型
    const validCuisineTypes: Cuisine[] = [
      '川菜', '湘菜', '粤菜', '日料', '韩料', '西餐', '快餐', '火锅', '麻辣烫', '轻食',
      '中餐厅', '西餐厅', '快餐厅', '火锅店', '日本料理', '韩国料理', '茶艺馆', '冷饮店',
      '咖啡厅', '甜品店', '面包店', '烧烤店', '小吃店', '饺子馆', '面馆', '粥店', '其他'
    ];
    return validCuisineTypes.includes(cuisine);
  });
  
  return validCuisines.length > 0 ? validCuisines : ['其他'];
}

// 根据POI类型推断菜系
function inferCuisineFromType(typecode: string, name: string, type?: string): Cuisine[] {
  // 首先根据名称关键词推断（优先级最高）
  const nameKeywords: Record<string, Cuisine> = {
    咖啡: '咖啡厅',
    甜品: '甜品店',
    面包: '面包店',
    烧烤: '烧烤店',
    小吃: '小吃店',
    饺子: '饺子馆',
    面条: '面馆',
    面食: '面馆',
    面馆: '面馆',
    粥: '粥店',
    川菜: '川菜',
    川味: '川菜',
    四川: '川菜',
    麻辣: '川菜',
    湘菜: '湘菜',
    湖南: '湘菜',
    粤菜: '粤菜',
    广东: '粤菜',
    日料: '日料',
    日本: '日料',
    寿司: '日料',
    韩料: '韩料',
    韩国: '韩料',
    韩式: '韩料',
    西餐: '西餐',
    牛排: '西餐',
    意大利: '西餐',
    快餐: '快餐',
    汉堡: '快餐',
    肯德基: '快餐',
    麦当劳: '快餐',
    火锅: '火锅',
    麻辣烫: '麻辣烫',
    轻食: '轻食',
    沙拉: '轻食',
  };

  for (const [keyword, cuisine] of Object.entries(nameKeywords)) {
    if (name.includes(keyword)) {
      return [cuisine];
    }
  }

  // 如果有type字段，按分号分割取第二个值作为菜系
  if (type) {
    const typeSegments = type.split(';');
    // 取第二个值（索引为1），如果不存在则取最后一个值
    const targetSegment = typeSegments.length > 1 ? typeSegments[1].trim() : typeSegments[typeSegments.length - 1].trim();
    
    // 扩展的菜系类型映射表，包含更多常见餐饮类型
    const typeMapping: Record<string, Cuisine> = {
      // 中餐类型
      '中餐厅': '中餐厅',
      '川菜': '川菜',
      '湘菜': '湘菜',
      '粤菜': '粤菜',
      '火锅店': '火锅店',
      '麻辣烫': '麻辣烫',
      '饺子馆': '饺子馆',
      '面馆': '面馆',
      '粥店': '粥店',
      '小吃店': '小吃店',
      '烧烤店': '烧烤店',
      
      // 外国料理
      '日本料理': '日本料理',
      '韩国料理': '韩国料理',
      '西餐厅': '西餐厅',
      
      // 快餐和轻食
      '快餐厅': '快餐厅',
      '轻食': '轻食',
      
      // 饮品和甜品
      '茶艺馆': '茶艺馆',
      '冷饮店': '冷饮店',
      '咖啡厅': '咖啡厅',
      '甜品店': '甜品店',
      '面包店': '面包店',
      
      // 通用餐饮服务
      '餐饮服务': '其他',
    };
    
    // 首先尝试精确匹配
    if (typeMapping[targetSegment]) {
      return [typeMapping[targetSegment]];
    }
    
    // 如果精确匹配失败，尝试模糊匹配
    const fuzzyMatching: Array<{keyword: string, cuisine: Cuisine}> = [
      {keyword: '咖啡', cuisine: '咖啡厅'},
      {keyword: '甜品', cuisine: '甜品店'},
      {keyword: '面包', cuisine: '面包店'},
      {keyword: '烧烤', cuisine: '烧烤店'},
      {keyword: '小吃', cuisine: '小吃店'},
      {keyword: '饺子', cuisine: '饺子馆'},
      {keyword: '面条', cuisine: '面馆'},
      {keyword: '面食', cuisine: '面馆'},
      {keyword: '粥', cuisine: '粥店'},
      {keyword: '火锅', cuisine: '火锅店'},
      {keyword: '麻辣烫', cuisine: '麻辣烫'},
      {keyword: '川菜', cuisine: '川菜'},
      {keyword: '湘菜', cuisine: '湘菜'},
      {keyword: '粤菜', cuisine: '粤菜'},
      {keyword: '日料', cuisine: '日本料理'},
      {keyword: '日本', cuisine: '日本料理'},
      {keyword: '韩料', cuisine: '韩国料理'},
      {keyword: '韩国', cuisine: '韩国料理'},
      {keyword: '西餐', cuisine: '西餐厅'},
      {keyword: '快餐', cuisine: '快餐厅'},
      {keyword: '茶', cuisine: '茶艺馆'},
      {keyword: '饮品', cuisine: '冷饮店'},
    ];
    
    for (const {keyword, cuisine} of fuzzyMatching) {
      if (targetSegment.includes(keyword)) {
        return [cuisine];
      }
    }
    
    // 如果都没有匹配，返回"其他"
    return ['其他'];
  }

  // 优先根据typecode匹配
  if (TYPE_TO_CUISINE_MAP[typecode]) {
    return TYPE_TO_CUISINE_MAP[typecode];
  }

  // 默认返回"其他"
  return ['其他'];
}

// 生成餐厅图片URL
function generateImageUrl(cuisine: Cuisine): string {
  const cuisineImages: Record<Cuisine, string> = {
    川菜: '/sichuan-food.jpg',
    湘菜: '/hunan-food.jpg',
    粤菜: '/cantonese-food.jpg',
    日料: '/japanese-food.jpg',
    韩料: '/korean-food.jpg',
    西餐: '/western-food.jpg',
    快餐: '/fast-food.jpg',
    火锅: '/hot-pot.jpg',
    麻辣烫: '/malatang.jpg',
    轻食: '/light-meal.jpg',
    中餐厅: '/sichuan-food.jpg',
    西餐厅: '/western-food.jpg',
    快餐厅: '/fast-food.jpg',
    火锅店: '/hot-pot.jpg',
    日本料理: '/japanese-food.jpg',
    韩国料理: '/korean-food.jpg',
    茶艺馆: '/light-meal.jpg',
    冷饮店: '/light-meal.jpg',
    咖啡厅: '/light-meal.jpg',
    甜品店: '/light-meal.jpg',
    面包店: '/light-meal.jpg',
    烧烤店: '/sichuan-food.jpg',
    小吃店: '/sichuan-food.jpg',
    饺子馆: '/sichuan-food.jpg',
    面馆: '/sichuan-food.jpg',
    粥店: '/light-meal.jpg',
    其他: '/default-food.jpg',
  };
  return cuisineImages[cuisine] || '/default-food.jpg';
}

// 将高德地图POI转换为Restaurant对象
function transformPOIToRestaurant(poi: AmapPOI): Restaurant {
  const rawCuisines = inferCuisineFromType(poi.typecode, poi.name, poi.type);
  const cuisines = validateAndCleanCuisine(rawCuisines); // 验证和清理菜系数据
  const primaryCuisine = cuisines[0];

  // 解析距离（米）
  const distance = poi.distance ? parseInt(poi.distance, 10) : 0;

  // 解析评分
  const rating = poi.business?.rating ? parseFloat(poi.business.rating) : undefined;

  // 解析价格
  const avgPrice = poi.business?.cost ? parseInt(poi.business.cost, 10) : undefined;

  return {
    id: `amap-${poi.id}`,
    name: poi.name,
    // imageUrl: generateImageUrl(primaryCuisine), // 不再需要图片URL，使用颜色背景
    cuisines,
    source: 'nearby',
    avgPrice,
    rating,
    distance, // 使用distance字段替换etaMinutes
    mapUrl: `https://uri.amap.com/search?keyword=${encodeURIComponent(poi.name)}&location=${poi.location}`,
  };
}

// 缓存管理
interface CacheEntry {
  data: Restaurant[];
  timestamp: number;
  location: string;
}

const cache = new Map<string, CacheEntry>();
const CACHE_DURATION = 60 * 60 * 1000; // 1小时缓存

function getCacheKey(longitude: number, latitude: number): string {
  // 将坐标精确到小数点后3位，约100米精度
  const roundedLng = Math.round(longitude * 1000) / 1000;
  const roundedLat = Math.round(latitude * 1000) / 1000;
  return `${roundedLng},${roundedLat}`;
}

function getCachedData(longitude: number, latitude: number): Restaurant[] | null {
  const key = getCacheKey(longitude, latitude);
  const entry = cache.get(key);

  if (!entry) return null;

  const now = Date.now();
  if (now - entry.timestamp > CACHE_DURATION) {
    cache.delete(key);
    return null;
  }

  return entry.data;
}

function setCachedData(longitude: number, latitude: number, data: Restaurant[]): void {
  const key = getCacheKey(longitude, latitude);
  cache.set(key, {
    data,
    timestamp: Date.now(),
    location: `${longitude},${latitude}`,
  });
}

/**
 * 搜索周边餐厅
 * @param longitude 经度
 * @param latitude 纬度
 * @returns Promise<Restaurant[]>
 */
export async function searchNearbyRestaurants(
  longitude: number,
  latitude: number,
): Promise<Restaurant[]> {
  // 检查缓存
  const cachedData = getCachedData(longitude, latitude);
  if (cachedData) {
    return cachedData;
  }

  const location = `${longitude},${latitude}`;
  const url = new URL(AMAP_CONFIG.baseUrl);

  // 设置请求参数
  url.searchParams.set('key', AMAP_CONFIG.key);
  url.searchParams.set('location', location);
  url.searchParams.set('radius', AMAP_CONFIG.radius.toString());
  url.searchParams.set('extensions', AMAP_CONFIG.extensions);
  url.searchParams.set('types', '050000'); // 餐饮服务类型
  url.searchParams.set('output', 'json');

  try {
    const response = await fetch(url.toString(), {
      method: 'GET',
      headers: {
        Accept: 'application/json',
      },
    });

    if (!response.ok) {
      throw new Error(`HTTP错误: ${response.status} ${response.statusText}`);
    }

    const data: AmapResponse = await response.json();

    // 检查API响应状态
    if (data.status !== '1') {
      const errorMessage = ERROR_MESSAGES[data.infocode] || `API错误: ${data.info}`;
      throw new Error(errorMessage);
    }

    // 转换POI数据为Restaurant对象
    const restaurants = data.pois
      .filter((poi) => poi.name && poi.location) // 过滤无效数据
      .map(transformPOIToRestaurant)
      .slice(0, 50); // 限制返回数量

    // 缓存结果
    setCachedData(longitude, latitude, restaurants);

    return restaurants;
  } catch (error) {
    console.error('高德地图API请求失败:', error);

    if (error instanceof Error) {
      // 重新抛出带有友好提示的错误
      throw new Error(`获取周边餐厅失败: ${error.message}`);
    }

    throw new Error('获取周边餐厅失败: 网络连接异常');
  }
}

/**
 * 清除缓存
 */
export function clearCache(): void {
  cache.clear();
}

/**
 * 获取缓存统计信息
 */
export function getCacheStats() {
  return {
    size: cache.size,
    entries: Array.from(cache.entries()).map(([key, entry]) => ({
      location: key,
      timestamp: entry.timestamp,
      count: entry.data.length,
    })),
  };
}
